package middleware

import (
	"bytes"
	"cgs-server/helper"
	"cgs-server/internal/pkg/code"
	"cgs-server/pkg/log"
	"cgs-server/server"
	"context"
	"git.mapchang.com/go/base/core"
	"git.mapchang.com/go/errors"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"io/ioutil"
	"strings"
)

func SdkMiddleware(c *gin.Context) {
	r := c.Request

	auth, ok := server.GetApiAuthority(r.URL.Path)
	if !ok {
		// path is not registered.
		log.Errorf("%v is not registered", r.URL.Path)
		core.WriteResponse(c, errors.WithCode(code.ErrPageNotFound, "访问的路径不存在"), nil)
		c.Abort()
		return
	}
	isApi := strings.HasPrefix(auth.ApiPath, "/api/v1") || strings.HasPrefix(auth.ApiPath, "/api/v2")
	// api needs no authority
	if auth.Auth == string(server.None) && isApi {
		appKey := ""
		sign := ""
		if len(r.Header) > 0 {
			for k, v := range r.Header {
				if k == "App-Key" {
					appKey = v[0]
				} else if k == "Sign" {
					sign = v[0]
				}
			}
		}
		if appKey == "" || sign == "" {
			r.ParseForm()
			appKey = r.FormValue("App-Key")
			sign = r.FormValue("Sign")
		}
		// 从 body 里读取
		if appKey == "" || sign == "" {
			result := struct {
				AppKey string `json:"App-Key"`
				Sign   string
			}{}
			bodyBytes, _ := ioutil.ReadAll(r.Body)
			r.Body.Close() //  must close
			_ = helper.FromJSON(bodyBytes, &result)
			appKey = result.AppKey
			sign = result.Sign
			r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
		}
		if appKey == "" || sign == "" {
			core.WriteResponse(c, errors.WithCode(code.ErrSignatureInvalid, "AppKey or Sign is missing."), nil)
			c.Abort()
			return
		}
		db, err := server.Mongo()
		if err != nil {
			core.WriteResponse(c, errors.WithCode(code.ErrDatabase, err.Error()), nil)
			c.Abort()
			return
		}
		filter := bson.M{
			"AppKey": appKey,
		}
		doc := bson.M{}
		find, _ := db.FindOne(server.CgsAppKeyCollectionName, filter, &doc)
		if !find {
			core.WriteResponse(c, errors.WithCode(code.ErrorAppKeyNotFound, "Can not find AppKey %s ", appKey), nil)
			c.Abort()
			return
		} else {
			appSecret := doc["AppSecret"].(string)
			timestamp := doc["Timestamp"].(string)
			authType := doc["AuthType"].(string)
			if authType == "0" {
				// 密钥未启用
				core.WriteResponse(c, errors.WithCode(code.ErrorAppKeyNotEnabled, "AppKey is not enabled"), nil)
				c.Abort()
				return
			}

			signs := helper.EncryptBase62(appKey + "&" + appSecret + "&" + timestamp)
			sign = strings.TrimSpace(sign)
			if signs != sign {
				core.WriteResponse(c, errors.WithCode(code.ErrorSignInvalid, "AppKey Not Valid"), nil)
				c.Abort()
				return
			}
			userID := doc["UserID"]
			ctx := context.WithValue(context.Background(), "userID", userID)
			ctx = context.WithValue(ctx, "authType", authType)
			r = r.WithContext(ctx)
			c.Request = r
			c.Next()
			return
		}

	}

	c.Next()

}
